#ifndef __PACKET_PROCESSOR_H__
#define __PACKET_PROCESSOR_H__

#include "xQueue.h"
#include "boost/function.hpp"
#include <google/protobuf/message.h>
#include "xStream.h"
#include "NetDef.h"

struct xMSG
{
#pragma pack(push)
#pragma pack(1)
	struct msghead
	{
		msghead()
		{
			msg_id = reserved = 0;
			magic_id = 0;
		}
		U16   msg_id;
		U16   reserved;
		U64	  magic_id;
	};
#pragma pack(pop)

	xMSG(U16 m_id = 0);
	xMSG(U16 m_id, class ::google::protobuf::Message* pMsg, U64 magic_id = 0);
	xMSG(const xMSG& src);
	xMSG(U8* msg_ptr_, U32 msg_len);

	~xMSG()
	{
		if (msg_ptr)
		{
			delete[] msg_ptr;
			msg_ptr = NULL;
		}
		dwLen = 0;
	}

	void AddParameter(class ::google::protobuf::Message* pMsg);
	
	U8* getParameterData()
	{
		return msg_ptr+sizeof(msghead);
	}

	U32 getParameterSize()
	{
		return dwLen - sizeof(msghead);
	}

	msghead* getHead()
	{
		return (msghead*)msg_ptr;
	}

	U16 getMsgID()
	{
		return msg_head.msg_id;
	}

	void release();

	friend CGsStream& operator<<(CGsStream& stream, msghead& value);
	friend CGsStream& operator>>(CGsStream& stream, msghead& value);

	msghead msg_head;
	U8* msg_ptr;
	U32 dwLen;
	U64 call_guid;
	ENetDef::_eNet	from_net_type;
};

typedef boost::function<void(xMSG& msg)>  CMD_CB;

class CPacketProcesser
{
	SINGLETON_CLASS(CPacketProcesser)
public:
	CPacketProcesser();
	~CPacketProcesser();

	S32	MsgIn(xMSG& msg);

	void RegDefaultCB(CMD_CB cb) {m_defaultCB = cb;}
	void UnRegDefaultCB(){m_defaultCB = NULL;}
	void RegCB(U16 cmd_id, CMD_CB cb);
	void UnReg(U16 cmd_id);
	void start();
protected:
	void ProcessFunction();
protected:
	boost::unordered_map<U16, CMD_CB>		m_mapCB; 
	CMD_CB									m_defaultCB;
private:
	CWnQueue<xMSG*> m_record_set;
	CWnEvent m_event;
	volatile	BOOL	m_bRun;
};

#endif //__PACKET_PROCESSOR_H__